﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace HEFramework
{
    public static class PrefabComponentSystem
    {
        [EntitySystem]
        public class PrefabComponentAwakeSystem : AwakeSystem<PrefabComponent>
        {
            protected override void Awake(PrefabComponent _self)
            {
                _self.AddChild<ResourcesComponent>();
            }
        }


        [EntitySystem]
        public class PrefabComponentDestroySystem : DestroySystem<PrefabComponent>
        {
            protected override void Destroy(PrefabComponent _self)
            {
                for (int i = 0; i < _self.Objects.Count; i++)
                {
                    GameObject.Destroy(_self.Objects[i].gameObject);
                }

                _self.Pools.Clear();
                _self.Objects.Clear();
            }
        }


        /// <summary>
        /// 读取预制体（同步）
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_assetBundleName"></param>
        /// <param name="_assetName"></param>
        /// <param name="_isActive"></param>
        /// <returns></returns>
        public static GameObject GetPrefabSyn(this PrefabComponent _self, string _assetBundleName, string _assetName, bool _isActive = true)
        {
            Stack<GameObject> stack;
            string flag = _assetBundleName + "|" + _assetName;
            _self.Pools.TryGetValue(flag, out stack);
            if (stack == null)
            {
                stack = new Stack<GameObject>();
                _self.Pools.Add(flag, stack);
            }

            GameObject obj;
            if (stack.Count > 0)
            {
                obj = stack.Pop();
            }
            else
            {
                var rc = _self.GetChild<ResourcesComponent>();
                obj = GameObject.Instantiate(rc.Assets.LoadAssetSyn<GameObject>(_assetBundleName, _assetName, ResourceConfig.Extension.PREFAB));
                //记录一下
                _self.Objects.Add(obj);
            }

            obj.SetActive(_isActive);
            return obj;
        }


        /// <summary>
        /// 读取预制体（异步）
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_assetBundleName"></param>
        /// <param name="_assetName"></param>
        /// <param name="_callback"></param>
        /// <param name="_isActive"></param>
        public static void GetPrefabAsync(this PrefabComponent _self, string _assetBundleName, string _assetName, Action<GameObject> _callback, bool _isActive = true)
        {
            Stack<GameObject> stack;
            string flag = _assetBundleName + "|" + _assetName;
            _self.Pools.TryGetValue(flag, out stack);
            if (stack == null)
            {
                stack = new Stack<GameObject>();
                _self.Pools.Add(flag, stack);
            }

            GameObject obj;
            if (stack.Count > 0)
            {
                obj = stack.Pop();
                obj.SetActive(_isActive);
                _callback(obj);
            }
            else
            {
                var rc = _self.GetChild<ResourcesComponent>();
                rc.Assets.LoadAssetAsync<GameObject>(_assetBundleName, _assetName, ResourceConfig.Extension.PREFAB, _ =>
                {
                    obj = GameObject.Instantiate(_);
                    //记录一下
                    _self.Objects.Add(obj);
                    obj.SetActive(_isActive);
                    _callback(obj);
                });
            }
        }


        public static void Recycle(this PrefabComponent _self, string _assetBundleName, string _assetName, GameObject _obj)
        {
            Stack<GameObject> stack;
            string flag = _assetBundleName + "|" + _assetName;
            _self.Pools.TryGetValue(flag, out stack);
            if (stack == null)
            {
                return;
            }

            _obj.transform.SetParent(null,false);
            _obj.gameObject.SetActive(false);

            stack.Push(_obj);
        }
    }
}